package com.ztrue.framework.handler;

import com.ztrue.framework.handler.definition.IHandlerDefinition;
import com.ztrue.common.log.Logger;
import com.ztrue.common.utilities.StringUtil;

import java.util.*;

/**
 * 默认的处理器注册表实现
 *
 * @author zhangw
 * @date 2016/11/15 16:33
 * @version: 1.0
 */
public class DefaultHandlerRegistry implements IHandlerRegistry {
    private static final Logger logger = Logger.getLogger(DefaultHandlerRegistry.class);

    private final Map<String, Object> handlers = new HashMap<String, Object>();
    private final IHandlerDefinitionRegistry handlerDefinitionRegistry;

    public DefaultHandlerRegistry(IHandlerDefinitionRegistry handlerDefinitionRegistry) {
        this.handlerDefinitionRegistry = handlerDefinitionRegistry;
    }

    /**
     * 添加一个处理器到注册表
     *
     * @param handlerName 处理器名称
     * @param handler     处理器对象
     */
    @Override
    public void addHandler(String handlerName, Object handler) {
        this.handlers.put(handlerName, handler);
    }

    /**
     * 根据处理器名称获取处理器对象
     *
     * @param handlerName 处理器名称
     * @return
     */
    @Override
    public Object getHandler(String handlerName) {
        Object handler = this.handlers.get(handlerName);
        if (handler == null) {
            IHandlerDefinition handlerDefinition = this.handlerDefinitionRegistry.getHandlerDefinition(handlerName);
            if (handlerDefinition != null) {
                try {
                    handler = handlerDefinition.getHandlerClass().newInstance();
                } catch (Exception e) {
                    logger.error("无法创建[" + handlerName + "]处理器对象", e);
                }
                this.addHandler(handlerName, handler);
            }
        }
        return handler;
    }

    /**
     * 根据处理器名称和处理器类型获取处理器对象
     *
     * @param handlerName  处理器名称
     * @param requiredType 处理器类型
     * @return
     */
    @Override
    public <T> T getHandler(String handlerName, Class<T> requiredType) {
        Object handler = this.getHandler(handlerName);
        if (handler != null) {
            if (requiredType != null && !requiredType.isAssignableFrom(handler.getClass())) {
                throw new HandlerNotOfRequiredTypeException(handlerName, requiredType, handler.getClass());
            }
        }
        return (T) handler;
    }

    /**
     * 根据处理器类型获取处理器对象
     *
     * @param requiredType 处理器类型
     * @return
     */
    @Override
    public <T> T getHandler(Class<T> requiredType) {
        String[] handlerNames = getHandlerNamesByType(requiredType);
        if (handlerNames.length == 1) {
            return getHandler(handlerNames[0], requiredType);
        } else if (handlerNames.length > 1) {
            throw new NoUniqueHandlerDefinitionException(requiredType, handlerNames);
        } else {
            throw new NoSuchHandlerDefinitionException(requiredType);
        }
    }

    /**
     * 根据指定类型查找匹配的处理器名称
     *
     * @param type
     * @return
     */
    private String[] getHandlerNamesByType(Class type) {
        List<String> matchs = new ArrayList<>();
        for (String handlerName :
                this.handlers.keySet()) {
            Object handler = this.getHandler(handlerName);
            if (type.isAssignableFrom(handler.getClass())) {
                matchs.add(handlerName);
            }
        }
        String[] handlerNames = handlerDefinitionRegistry.getHandlerNameByType(type);
        for (String handlerName :
                handlerNames) {
            if (!matchs.contains(handlerName)) {
                matchs.add(handlerName);
            }
        }
        return StringUtil.toStringArray(matchs);
    }


}
